import * as d3 from "d3";

function Budgetpaint(data,Status)
{
  // 筛选所需数据
  data = data.filter(item =>{
    return item.typenum == Status;
  });// typenum : 0天津 1-16各区
  // 数据转换
  data=data.map(d=>{return{
    name:d.year,//年份
    category:d.typename,//不同地区收入支出种类
    value:parseInt(d.Budget)}//收入支出金额
  });
  // Normalize absolute values to percentage.
  d3.rollup(data, group => {
    const sum = d3.sum(group, d => d.value);
    for (const d of group) d.value /= sum;
  }, d => d.name);
  Object.assign(data, {
    negative: "← 财政支出相对比例",
    positive: "财政收入相对比例 →",
    negatives: ["其他支出", "教育支出", "社会保障和就业支出"],
    positives: ["税收收入", "非税收入"]
  });
  // Assign a valence to each category.
  const signs = new Map([].concat(
    data.negatives.map(d => [d, -1]),
    data.positives.map(d => [d, +1])
  ));
  // Compute the bias = sum of negative values for each candidate.
  const bias = d3.sort(
    d3.rollup(data, v => d3.sum(v, d => d.value * Math.min(0, signs.get(d.category))), d => d.name),
    ([a,]) => a
  );

  // Specify the chart’s dimensions, with a space of height 30px for each candidate.
  const width = 800;
  const marginTop = 20;
  const marginRight = 40;
  const marginBottom = 40;
  const marginLeft = 20;
  const height = bias.length * 30 + marginTop + marginBottom;
  // console.log(height);// 210

  // Prepare the stack; the values are stacked from the inside out, starting with more
  // moderate values (“mostly false”, “half true”), and ending with the extreme values.
  const series = d3.stack()
    .keys([].concat(data.negatives.slice().reverse(), data.positives))
    .value(([, value], category) => signs.get(category) * (value.get(category) || 0))
    .offset(d3.stackOffsetDiverging)
  (d3.rollup(data, data => d3.rollup(data, ([d]) => d.value, d => d.category), d => d.name));

  // Construct the scales.
  const x = d3.scaleLinear()
    .domain(d3.extent(series.flat(2)))
    .rangeRound([2*marginLeft, width - marginRight])
  const y = d3.scaleBand()
    .domain(bias.map(([name]) => name))
    .rangeRound([2*marginTop, height - marginBottom])
    .padding(2 / 33)
  const color = d3.scaleOrdinal()
    .domain([].concat(data.negatives, data.positives))
    .range(d3.range(0, 1, 1 / (data.negatives.length + data.positives.length)).map(t => d3.interpolateRdYlGn(t)))

  // A function to format a percentage, used both on the axis and in the tooltips.
  const formatValue = ((format) => (x) => format(Math.abs(x)))(d3.format(".0%"));

  // Create the SVG container.
  const svg = d3.select("#svgBudget");
  svg.selectAll("*").remove();
  svg.attr("viewBox", [0, 0, width, height])
    .attr("width", width)
    .attr("height", height)
    .attr("style", "max-width: 100%; height: auto; font: 10px sans-serif;");

  // Append a rect for each value, with a tooltip.
  svg.append("g")
    .selectAll("g")
    .data(series)
    .join("g")
      .attr("fill", d => color(d.key))
    .selectAll("rect")
    .data(d => d.map(v => Object.assign(v, {key: d.key})))
    .join("rect")
      .attr("x", d => x(d[0]))
      .attr("y", ({data: [name]}) => y(name))
      .attr("width", d => x(d[1]) - x(d[0]))
      .attr("height", y.bandwidth())
    .append("title")
      .text(({key, data: [name, value]}) => `${name}
  ${formatValue(value.get(key))} ${key}`);

  // Create the axes.
  svg.append("g")
      .attr("transform", `translate(0,${2*marginTop})`)
    .call(d3.axisTop(x)
        .ticks(width / 80)
        .tickFormat(formatValue)
        .tickSizeOuter(0))
    .call(g => g.select(".domain").remove())
    .call(g => g.append("text")
        .attr("x", x(0) + 20)
        .attr("y", -24)
        .attr("fill", "black")
        .attr("text-anchor", "start")
        .style("font-size", "14px") // 调整字体大小在这里
        .text(data.positive))
    .call(g => g.append("text")
        .attr("x", x(0) - 20)
        .attr("y", -24)
        .attr("fill", "black")//"currentColor")
        .attr("text-anchor", "end")
        .style("font-size", "14px") // 调整字体大小在这里
        .text(data.negative));
  svg.append("g")
    .call(d3.axisLeft(y).tickSizeOuter(0))
    .call(g => g.selectAll(".tick").data(bias).attr("transform", ([name, min]) => `translate(${x(min)},${y(name) + y.bandwidth() / 2})`))
    .call(g => g.select(".domain").attr("transform", `translate(${x(0)},0)`));

  // 创建一个组元素用于容纳图例
  const legendGroup = svg.append("g")
    .attr("class", "legend")
    .attr("transform", "translate(20, 0)");
  // 创建一个矩形和文本组合表示颜色和标签
  const legendItems = legendGroup.selectAll(".legend-item")
    .data(d3.group(data, d => d.category))
    .enter().append("g")
    .attr("class", "legend-item")
    .attr("transform", (d, i) => {
      switch(i){
        case 0:
          return `translate(${480+40}, 200)`; break;
        case 1:
          return `translate(${480+140}, 200)`; break;
        case 2:
          return `translate(${590-4 * 120}, 200)`; break;
        case 3:
          return `translate(${590-2 * 120}, 200)`; break;
        case 4:
          return `translate(${500-2 * 120}, 200)`; break;
      }
    });
  // 添加矩形表示颜色
  legendItems.append("circle")
    .attr("r", 5)   // 半径
    .style("fill", d => {//console.log(d);
      return color(d[0]);});
  // 添加文本表示标签
  legendItems.append("text")
    .attr("x", 15) // 调整文本的位置
    .attr("y", 0)
    .attr("dy", "0.3em")
    .attr("font-size", "14px")
    .attr("font-family", "Arial, sans-serif")
    .attr("text-anchor", "start")
    .text(d => {//console.log(d);
      return `${d[0]}`;}); //根据数据值生成标签文本
  
  return svg.node();
}

export default Budgetpaint;